package cn.zhaoyuening.rpcdemo.rpc;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import org.omg.SendingContext.RunTime;

public class RpcProvider {
	private Executor executor;
	private int port;
	//状态 1正在提供服务 0服务关闭
	private int stuts;
	private ServerSocket serverSocket;
	private Map<String,Object> interfaceImplClassMap;
	
	public RpcProvider(int port){
		this.executor = Executors.newCachedThreadPool();
		this.port = port;
		try {
			serverSocket = new ServerSocket(port);
		} catch (IOException e) {
			e.printStackTrace();
		}
		interfaceImplClassMap = new HashMap<>();
	}
	
	/**
	 * 添加接口与实现类实例直接的映射	
	 * @param interfaceClass
	 * @param implClass
	 */
	public void addInterfaceClassMap(String interfaceName,Object implClass){
		interfaceImplClassMap.put(interfaceName, implClass);
	}
	
	public void providService() throws IOException{
		//判断是否正在提供服务
		if(stuts==1){
			return ;
		}
		this.stuts=1;
		//监听服务请求
		executor.execute(new Runnable() {
			
			@Override
			public void run() {
				while(true&&stuts==1){
					try {
						executor.execute(new ServiceProvider(serverSocket.accept()));
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		});
		
	}
	
	public void stopService(){
		stuts = 0;
		try {
			serverSocket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private  class ServiceProvider implements Runnable{
		private Socket socket;
		
		public ServiceProvider(Socket socket) {
			this.socket = socket;
		}
		 
		@Override
		public void run() {
			try {
				ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
				ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
				
				//获取远程调用信息
				String className = ois.readUTF();
				String methodName = ois.readUTF();
				Class<?>[] parameterTypes = (Class<?>[]) ois.readObject();
				Object[] args = (Object[]) ois.readObject();
				
				//调用远程指定服务的指定方法
				Object obj = interfaceImplClassMap.get(className);
				Class objClass = Class.forName(className);
				Method method = objClass.getMethod(methodName, parameterTypes);
				if(obj==null||method==null){
					return;
				}
				Object result = method.invoke(obj, args);
				
				//将结果返回给客户端
				oos.writeObject(result);
				
				ois.close();
				oos.close();
				
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		
	}
	
}
